package com.qlm.interceptor;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.aop.Enhancer;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.PropKit;
import com.jfinal.weixin.sdk.api.SnsAccessToken;
import com.jfinal.weixin.sdk.api.SnsAccessTokenApi;
import com.qlm.annoation.WeixinAuoth;
import com.qlm.entity.User;
import com.qlm.service.UserService;
import com.qlm.service.impl.UserServiceImpl;

/**
 * 微信统一端统一拦截器 ，该拦截器作用就是保证正确获取到用户信息
 * 使用方法：在微信controller上添加这个拦截器注解
 * 保证User.dao的用户表各个字段与下面各个属性值一致
 * 在config.porpertites文件中加一个配置authoUrl=http://xxx.com,这个的二维码的前缀
 * 比如http://www.qianlicode.com/p/i?123123这个码就只用填写authoUrl=http://www.qianlicode.com/p/i
 * 在获取用户信息失败后，会自动再跳转到这个页面授权
 * 微信扫码入口方法要添加@WeixinAnnotation注解
 * 1.通过在controller中getSession(user_key)//可以获取当前的session的用户对象User，他有各个属性
 * 2.
 * @author wangzih
 *
 */
public class WeixinInterceptor implements Interceptor {
	
	static Logger logger = LoggerFactory.getLogger(WeixinInterceptor.class);
	
	UserService userService = (UserService)Enhancer.enhance(UserServiceImpl.class);
	
	public static boolean finish = false;
	
	public static boolean checkTime = false;//是否检测时间

	public static final String user_key = "user_key";//session中用户key

	private static final String authoUrl = "authoUrl";//微信授权页面
	
	public void intercept(Invocation inv) {
		Controller controller = inv.getController();
		if(controller instanceof WeixinController){
			WeixinController cast = WeixinController.class.cast(controller);
			cast.setAttr("urlXX", PropKit.get("authoUrl"));
			if(!isAjaxReq(cast.getRequest())){
				cast.setJsTicket();
			}
		}
		Method method = inv.getMethod();
		WeixinAuoth WeixinAuoth = method.getAnnotation(WeixinAuoth.class);
		if(WeixinAuoth != null){//代表是码连接
			controller.removeSessionAttr(user_key);//码连接要清除session
			inv.invoke();
			return;
		}
		User user = before(controller);
		if (user != null) {
			controller.setSessionAttr(user_key, user);//放入到session中
			inv.invoke();
		} else {
			String url = controller.getRequest().getRequestURL().toString();
			String autho = PropKit.get(authoUrl);
			String uri = url.substring(autho.length());
			controller.redirect(PropKit.get("authoUrl")+uri);
		}

	}

	/**
	 * 扫码前的方法
	 */
	protected User before(Controller controller) {
//		boolean flag = true;
//		if(flag){
//			User u = User.dao.findById("123");
//			return u;
//		}
		User user = controller.getSessionAttr(user_key);
		if(user != null) return user;
		String state = controller.getPara("state");
		if(!"wx".equals(state)){//代表是授权跳转过来的
			return null;
		}
		String code = controller.getPara("code");
		if (code == null) {// 授权码为空，跳转到重新授权页面
			return null;
		}
		if (user == null) {
			SnsAccessToken token = null;
			try{
				 token = SnsAccessTokenApi.getSnsAccessToken(PropKit.get("appid"), PropKit.get("appsecret"),
					code);
			}catch(Exception e){//可能会超时
				logger.error("获取授权accessToken失败",e);
				return null;
			}
			if(!token.isAvailable()){
				logger.error("获取授权accessToken失败，原因:"+token.getJson());
				return null;
			}
			String openId = token.getOpenid();
			String scope = token.getScope();
			if("snsapi_base".equals(scope)){
				user = new User();
				user.set(UserService.OPENID, openId);
				return user;
			}
			user = findUser(openId);
			if (user == null) {
				user = getUserInfoByWeiXinAndSave(code, token);
				if (user == null) {// 向微信获取用户信息失败，跳转到授权页面
					controller.redirect(PropKit.get(authoUrl));
				}
			}
		}
		return user;
	}

	private User findUser(String openId) {
		User user = userService.getUserById(openId);
		return user;
	}

	/**
	 * 通过授权码向微信获取用户信息,并且保存到数据库
	 * 
	 * @param code
	 * @return
	 */
	private User getUserInfoByWeiXinAndSave(String code, SnsAccessToken token) {
		return userService.getUserInfoFromWXAndSave(code, token);
	}

	private boolean isAjaxReq(HttpServletRequest req) {
		boolean ajax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));
		return ajax;
	}

}
